/*
 * GUID.java
 * Generates Globally Unique Identifiers
 * Created on September 11, 2006, 3:41 PM
 *
 * @author Daniel Beutler, <dannyb@alianza.com>, Isys 403, Section 2
 * @version 1.0
 */

package Data;
import java.net.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.StringTokenizer;

public class GUID{
//GUID code here
    
//Create static longs to keep the counter and time from the last call of the class
    static long lasttime = 0;
    static long counter = 0;
  
    public static synchronized String generate() throws Exception {
        // GUID generate code goes here
        
        //Get the time
        //long now = System.currentTimeMillis();
        long now = GUID.longDateTime();
        //Convert the time to Hexidecimal
        String hexNow = Long.toString(now);
        
        //Real Date Time Creator
        long dateTime = GUID.longDateTime();
        
        
        //Pad the HexTime to 16 Characters
        String paddedHexNow = GUID.zeroPad(hexNow,16,'0');
        
        //Check the time in this GUID to the last GUID.  If true, increment the counter variable.  If False reset the counter to zero.
        if (lasttime != now){
            counter = 0;
        } else {
            counter++;
        }
        
        //Check to make sure the counter doesn't wrap and wait until the next millisecond to continue
        if (counter == 1048574){
            while (lasttime == now){
                Thread.sleep(1);
            }
        };
        
        //Save state of the time to compare to next time
        lasttime = now;
        
        //Change the counter to hex and pad with zeros until 6 characters
        String hexCounter = Long.toHexString(counter);
        String paddedHexCounter = GUID.zeroPad(hexCounter,5,'0');
        
        //Retrieve the current machine's IP address using the java.net.InetAddress class
        InetAddress address = InetAddress.getLocalHost();
        
        //Split the IP address into each octet
        byte[] IPaddress = address.getAddress();
        
        //GUID.dottedIPtohexIP takes a byte array of an IP address and creates a padded 8 hexidecimal string to represent the IP
        String HEXIP = GUID.dottedIPtohexIP(IPaddress);
        
        
        //Concatenate the HEX time, HEX counter, and HEX IP into the GUID
        String GUID = paddedHexNow.concat(paddedHexCounter);
        GUID = GUID.concat(HEXIP);
        //GUID should be 30 characters in length
        
        //Return the entire GUID
        return GUID;
    }
    
    public static synchronized String extractTime() throws Exception {
        // GUID extractTime code goes here
        return "TIME";
    }
    public static synchronized String extractCounter() throws Exception {
        // GUID extractCounter code goes here
        return "COUNTER";
    }
    public static synchronized String extractIP() throws Exception {
        // GUID extractIP code goes here
        return "IP ADDRESS";
    }
    
    //Pad a string(sValue) to a given length with a given character
    public static String zeroPad(String sValue, int length, char padChar) {
        int beginLength = sValue.length();
        if (beginLength < length){
            for (int i=beginLength; i<length; i++) {
                sValue = padChar + sValue;
            }
        }
        return sValue;
    }
    
    //Class that converts a string with a dotted ip to Hex
    public static String dottedIPtohexIP(byte[] dottedIP) {
        
        //Separate octets
        int firstOctetInteger = dottedIP[0];
        int secondOctetInteger = dottedIP[1];
        int thirdOctetInteger = dottedIP[2];
        int fourthOctetInteger = dottedIP[3];
        if (firstOctetInteger < 0) firstOctetInteger = firstOctetInteger + 256;
        if (secondOctetInteger < 0) secondOctetInteger = secondOctetInteger + 256;
        if (thirdOctetInteger < 0) thirdOctetInteger = thirdOctetInteger + 256;
        if (fourthOctetInteger < 0) fourthOctetInteger = fourthOctetInteger + 256;
        
        //Convert int to hex for each octet.
        
        //String hexIP = paddedHexNow.concat(paddedHexCounter);
        String firstHex = Integer.toHexString(firstOctetInteger);
        String secondHex = Integer.toHexString(secondOctetInteger);
        String thirdHex = Integer.toHexString(thirdOctetInteger);
        String fourthHex = Integer.toHexString(fourthOctetInteger);
        //pad each hex
        String firstHexPadded = GUID.zeroPad(firstHex,2,'0');
        String secondHexPadded = GUID.zeroPad(secondHex,2,'0');
        String thirdHexPadded = GUID.zeroPad(thirdHex,2,'0');
        String fourthHexPadded = GUID.zeroPad(fourthHex,2,'0');
        //concatenate the 4 parts an return the 8 characters
        String hexPaddedIP = firstHexPadded.concat(secondHexPadded);
        hexPaddedIP = hexPaddedIP.concat(thirdHexPadded);
        hexPaddedIP = hexPaddedIP.concat(fourthHexPadded);
        
        return hexPaddedIP;
    }
    
    public static synchronized long longDateTime() throws Exception {
        //Get Calendar Object
        Calendar currentDate = Calendar.getInstance();
        //Get integers for each part of the date
        int currentYear = currentDate.get(Calendar.YEAR);
        int currentMonth = currentDate.get(Calendar.MONTH);
        int currentDay = currentDate.get(Calendar.DAY_OF_MONTH);
        int currentHour = currentDate.get(Calendar.HOUR_OF_DAY);
        int currentMinute = currentDate.get(Calendar.MINUTE);
        int currentSecond = currentDate.get(Calendar.SECOND);
        int currentMillisecond = currentDate.get(Calendar.MILLISECOND);
        //Convert them to strings with padding
        String stringYear = Integer.toString(currentYear);
        String stringMonth = GUID.zeroPad(Integer.toString(currentMonth),2,'0');
        String stringDay = GUID.zeroPad(Integer.toString(currentDay),2,'0');
        String stringHour = GUID.zeroPad(Integer.toString(currentHour),2,'0');
        String stringMinute = GUID.zeroPad(Integer.toString(currentMinute),2,'0');
        String stringSecond = GUID.zeroPad(Integer.toString(currentSecond),2,'0');
        String stringMillisecond = GUID.zeroPad(Integer.toString(currentMillisecond),3,'0');
        String DateTime = stringYear.concat(stringMonth);
        DateTime = DateTime.concat(stringDay);
        DateTime = DateTime.concat(stringHour);
        DateTime = DateTime.concat(stringMinute);
        DateTime = DateTime.concat(stringSecond);
        DateTime = DateTime.concat(stringMillisecond);
        //System.out.println(DateTime);
        long longDateTime = Long.valueOf(DateTime);
        return longDateTime;
    }
    
}







